﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace XTYAPI.文件
{
    /// <summary>
    /// 231231纯手写已验证,异常情况调用方处理
    /// 240108已验证加注释内容，支持本身自带注释，内存添加注释等内容
    /// 240116增加新的节点前先空行，让节点直接看起来清晰；另外没有读配置，直接写配置，那么有注释时强制赋值;
    /// </summary>
   public class CfgIni
    {
        #region 文件操作
        /// <summary>
        /// 节点是否换行
        /// </summary>
        public bool IsSectionNewLine { get; set; } = true;
        public Dictionary<string, Dictionary<string, string>> IniData { get; private set; } = new Dictionary<string, Dictionary<string, string>>();
        public Dictionary<string, Dictionary<string, string>> IniNote { get; private set; } = new Dictionary<string, Dictionary<string, string>>();
         string NoteChar;
        /// <summary>
        /// 从硬盘里面加载
        /// </summary>
        /// <param name="path"></param>
        public void Load(string path)
        {
            string info= File.ReadAllText(path);
            string[] infos = info.Split(new char[] { '\n' });        
            Dictionary<string, Dictionary<string, string>> iniData = new Dictionary<string, Dictionary<string, string>>();
            Dictionary<string, Dictionary<string, string>> iniNote = new Dictionary<string, Dictionary<string, string>>();
            Dictionary<string, string> sectionData = new Dictionary<string, string>();
            Dictionary<string, string> sectionNote = new Dictionary<string, string>();
            string section = string.Empty;
            for (int i = 0; i < infos.Length; i++)
            {
                string line = infos[i].Trim();                
                if (line.StartsWith("[")&& line.EndsWith("]"))
                {
                    // 开始一个新的节
                    section = line.Substring(1, line.Length - 2);
                    sectionData= new Dictionary<string, string>();
                    sectionNote = new Dictionary<string, string>();
                    iniData[section] = sectionData;
                    iniNote[section] = sectionNote;
                }
                else if (line.Contains("="))
                {
                    // 解析键值对
                    string[] parts = line.Split('=');
                    string key = parts[0].Trim();
                    string[] values= parts[1].Split(';','#');
                    string value = string.Empty;
                    string note = string.Empty;
                    if (values.Length==1)//无注释版
                    {
                        value = parts[1].Trim();
                    }
                    if (values.Length>=2)//有注释版
                    {
                        NoteChar = parts[1].IndexOf(";") > 0 ? ";" : "#";
                        value = values[0].Trim();
                        note = values[1].Trim();
                    }                  
                    sectionData[key] = value;
                    sectionNote[key] = note;
                }
            }
            IniData = iniData;
            IniNote = iniNote;
        }
        /// <summary>
        /// 获取值
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public string GetValue(string section,string key)
        {
            if (IniData.ContainsKey(section))
            {
                if (IniData[section].ContainsKey(key))
                {
                    return IniData[section][key];
                }
                else
                {
                    return "";
                }
            }
            else
            {
                return "";
            }
        }
        /// <summary>
        /// 获取注释
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public string GetNote(string section, string key)
        {
            if (IniNote.ContainsKey(section))
            {
                if (IniNote[section].ContainsKey(key))
                {
                    return IniNote[section][key];
                }
                else
                {
                    return "";
                }
            }
            else
            {
                return "";
            }
        }
        /// <summary>
        /// 设定或改变值
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void SetValue(string section, string key,string value,string note="")
        {
            IniData[section][key] = value;
            IniNote[section][key] = note;
        }
        /// <summary>
        /// 删除节点里面的某个key
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        public bool Delete(string section,string key)
        {
            IniNote[section].Remove(key);
          return  IniData[section].Remove(key);
        }
        /// <summary>
        /// 删除节点
        /// </summary>
        /// <param name="section"></param>
        public bool Delete(string section)
        {
            IniNote.Remove(section);
            return IniData.Remove(section);
        }
        /// <summary>
        /// 保存到硬盘
        /// </summary>
        /// <param name="path"></param>
        public void Save(string path)
        {
            StringBuilder stringBuilder = new StringBuilder();
            int lineCount = 0;
            if (string.IsNullOrEmpty(NoteChar))
            {
                NoteChar = ";";
            }
            foreach (var seletion in IniData.Keys)
            {
                lineCount++;
                if (lineCount>1)
                {
                    stringBuilder.Append(Environment.NewLine);
                }
                stringBuilder.Append("[" + seletion + "]"+ Environment.NewLine);
              
                foreach (var key in IniData[seletion].Keys)
                {
                    if (IniNote[seletion][key].Length>0)
                    {
                        stringBuilder.Append(key + "=" + IniData[seletion][key] +NoteChar+ IniNote[seletion][key] + Environment.NewLine);
                    }
                    else
                    {
                        stringBuilder.Append(key + "=" + IniData[seletion][key]  + Environment.NewLine);
                    }                
                }
            }
            string info= stringBuilder.ToString();
            File.WriteAllText(path, info);
        }
        #endregion
        #region 数据转换
        public bool GetValueBool(string section,string key)
        {
            string value=  GetValue(section,key);
            bool result;
            if (bool.TryParse(value, out result))
            {
                return result;
            }          
            return false;
        }
        public int GetValueInt(string section, string key)
        {
            string value = GetValue(section, key);
            int result;
            if (int.TryParse(value, out result))
            {
                return result;
            }
            return 0;         
        }
        public uint GetValueUInt(string section, string key)
        {
            string value = GetValue(section, key);
            uint result;
            if (uint.TryParse(value, out result))
            {
                return result;
            }
            return 0;
        }
        public double GetValueDouble(string section, string key)
        {
            string value = GetValue(section, key);
            double result;
            if (double.TryParse(value, out result))
            {
                return result;
            }
            return 0;
        }
        public float GetValueFloat(string section, string key)
        {
            string value = GetValue(section, key);
            float result;
            if (float.TryParse(value, out result))
            {
                return result;
            }
            return 0;
        }
        public decimal GetValueDecimal(string section, string key)
        {
            string value = GetValue(section, key);
            decimal result;
            if (decimal.TryParse(value, out result))
            {
                return result;
            }
            return 0;
        }
     
        public void SetValue(string section, string key, bool value, string note = "")
        {
            SetValue(section,key, value?bool.TrueString:bool.FalseString,note);
        }
        public void SetValue(string section, string key, int value, string note = "")
        {
            SetValue(section, key, value.ToString(), note);
        }
        public void SetValue(string section, string key, uint value, string note = "")
        {
            SetValue(section, key, value.ToString(), note);
        }
        public void SetValue(string section, string key, double value, string note = "")
        {
            SetValue(section, key, value.ToString(), note);
        }
        public void SetValue(string section, string key, float value, string note = "")
        {
            SetValue(section, key, value.ToString(), note);
        }
        public void SetValue(string section, string key, decimal value, string note = "")
        {
            SetValue(section, key, value.ToString(), note);
        }
        #endregion
    }
}
